<!-- 模型列表 -->
<template>
  <div>
    <div class="trainning-view" style="z-index: 999;">
      <div class="header">
        <a-icon-font class="icon" type="iconqiehuantufenxibeifen2" />
        <span>模型训练</span>
        <div class="divider"></div>
        <div class="tab">
          <span class="m-span">我的模型</span>
          <div class="bottom-line"></div>
        </div>
      </div>
      <div style="background: #f3f5ff; height: 2px; width: 100%;"></div>

      <div v-if="!createMode" class="main-content">
        <div class="btns">
          <div class="primary-btn" align="center" @click="createModel">
            创建模型
          </div>
          <a-radio-group
            v-model="trainType"
            default-value="all"
            class="tabs"
            button-style="solid"
          >
            <a-radio-button value="all">全部</a-radio-button>
            <a-radio-button value="PENDING">未训练</a-radio-button>
            <a-radio-button value="FINISHED">训练完成</a-radio-button>
            <a-radio-button value="RUNNING">训练中</a-radio-button>
          </a-radio-group>

          <a-form layout="inline" class="search-form">
            <a-form-item label="模型名称：">
              <a-input
                v-model="searchFm.searchKey"
                allow-clear
                style="width: 150px;"
                placeholder="请输入"
              ></a-input>
            </a-form-item>
            <a-form-item label="模型类型：">
              <a-select
                v-model="searchFm.modelType"
                placeholder="请选择"
                allow-clear
                style="width: 250px;"
              >
                <a-select-opt-group
                  v-for="item in modelTypeList"
                  :key="'group' + item.groupName"
                  :label="item.groupName"
                >
                  <a-select-option
                    v-for="option in item.options"
                    :key="'option' + option.key"
                    :value="option.key"
                  >
                    <a-tooltip placement="top">
                      <template slot="title">
                        <span>{{ option.value }}</span>
                      </template>
                      <span>{{ option.value }}</span>
                    </a-tooltip>
                  </a-select-option>
                </a-select-opt-group>
              </a-select>
            </a-form-item>
            <a-form-item>
              <a-button type="primary" @click="queryList(trainType)"
                >查询</a-button
              >
            </a-form-item>
          </a-form>
        </div>

        <a-table
          :columns="columns"
          :loading="tableLoading"
          :data-source="modelList"
          row-key="id"
        >
          <span slot="name" slot-scope="text, record">
            {{ record.name }}
          </span>
          <span slot="modelType" slot-scope="text, record">
            {{ `${record.modelType}-${record.algorithm}` }}
          </span>
          <a
            slot="sourceName"
            slot-scope="sourceName, record"
            @click="checkDataSource(record)"
            >{{ sourceName }}</a
          >
          <span slot="data" slot-scope="text, record">
            <div v-if="record.modelType === '聚类'">
              {{
                record.data && record.data.silhouette
                  ? 'Silhouette Score：' + record.data.silhouette
                  : '-'
              }}
            </div>
            <span v-else-if="record.modelType === '回归'">
              {{
                record.data && record.data.r2 ? 'R²：' + record.data.r2 : '-'
              }}
            </span>
            <span v-else-if="record.modelType === '分类'">
              {{
                record.data && record.data.accuracy_test != null
                  ? '准确率：' + record.data.accuracy_test
                  : '-'
              }}
            </span>
            <span v-if="record.modelType === '降维'">
              {{
                record.data && record.data.ev_chart
                  ? '累积方差贡献率：' +
                    `${(
                      record.data.ev_chart[0][
                        record.data.ev_chart[0].length - 1
                      ] * 100
                    ).toFixed(2)}%`
                  : '-'
              }}
            </span>
            <div v-if="record.status === 'FINISHED'">
              <a :href="`${reportUrl}?id=${record.id}&type=a`">评估报告</a>
              <a-divider type="vertical" />
              <a :href="`${reportUrl}?id=${record.id}&type=b`">输出结果</a>
            </div>
          </span>
          <span slot="runTime" slot-scope="runTime, record">
            <div
              v-if="
                record.algorithm === 'AUTOC' || record.algorithm === 'AUTOR'
              "
            >
              <a-progress
                v-if="
                  !runTime &&
                  Number(record.param.timeout) > 20 &&
                  record.status === 'RUNNING'
                "
                :percent="progressObj[record.id]"
              />
              <span v-else>{{ runTime ? runTime + 's' : '-' }}</span>
            </div>
            <span v-else>{{ runTime ? runTime + 's' : '-' }}</span>
          </span>
          <span slot="action" slot-scope="record">
            {{ record.status }}
            <!-- 训练完 -->
            <div v-if="record.status === 'FINISHED'">
              <a @click="exportData(record)">导出模型</a>
              <a-divider type="vertical" />
              <a @click="reStartTrain(record)">重新训练</a>
              <a-divider type="vertical" />
              <a @click="goCreate(record)">编辑</a>
              <a-divider type="vertical" />
              <a @click="deleteModel(record)">删除</a>
            </div>
            <!-- 训练中 -->
            <div v-else-if="record.status === 'RUNNING'">
              <a @click="cancelTrain(record)">取消训练</a>
              <a-divider type="vertical" />
              <a @click="viewConfig(record)">查看配置</a>
              <a-divider type="vertical" />
              <a @click="deleteModel(record)">删除</a>
            </div>
            <!-- 未训练 PENDING FAILED KILLED-->
            <div v-else>
              <a @click="reStartTrain(record)">训练</a>
              <a-divider type="vertical" />
              <a @click="goCreate(record)">编辑</a>
              <a-divider type="vertical" />
              <a @click="deleteModel(record)">删除</a>
            </div>
          </span>
        </a-table>
      </div>

      <!-- 模型训练 -->
      <model-trainning
        v-else
        :project-id="projectId"
        @toggle-list="createModel"
      ></model-trainning>

      <div class="close" @click="closeGraphPanel">
        <a-icon title="关闭" type="close" />
      </div>
    </div>

    <!-- 导出模型 -->
    <a-modal
      :visible="exportVisible"
      :ok-text="'保存'"
      cancel-text="取消"
      centered
      :width="458"
      title="导出模型"
      @cancel.stop="
        exportVisible = false
        modelForm = {}
      "
      @ok="handleConfirm"
    >
      <div>
        <a-form
          :form="modelForm"
          :label-col="{ span: 6 }"
          :wrapper-col="{ span: 16 }"
        >
          <a-form-item label="导出至：">
            <a-input
              v-if="collectionList.length < 1"
              disabled
              placeholder="我的模型"
            ></a-input>
            <a-select
              v-else
              ref="select"
              v-model="modelForm.id"
              class="model-radius"
              placeholder="请选择"
              allow-clear
            >
              <a-select-option
                v-for="(item, index) in collectionList"
                :key="index"
                :value="item.id"
              >
                {{ item.name }}
              </a-select-option>
            </a-select>
          </a-form-item>
          <!-- <a-form-item label="模型名称：">
            <a-input
              ref="classInput"
              v-model="modelIndex.name"
              disabled
              class="model-radius"
            >
            </a-input>
          </a-form-item> -->
          <a-form-item label="模型名称：">
            <a-input
              ref="classInput"
              v-model="modelForm.name"
              placeholder="未命名"
              :allow-clear="true"
              class="model-radius"
            >
            </a-input>
          </a-form-item>
          <a-form-item label="功能描述：">
            <a-textarea
              v-model="modelForm.modelDesc"
              placeholder="创建时的功能性描述"
              :rows="6"
            />
          </a-form-item>
        </a-form>
      </div>
    </a-modal>

    <!-- <div class="ant-modal-mask" style="z-index: 998;"></div> -->
  </div>
</template>

<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator'
// import { graphCloseSession } from '@/api/visualization'
import ModelTrainning from '@/components/studio/data/model/ModelTrainning.vue'
import { allOperatorList } from '@/api/operator-list'
import { Modal } from 'ant-design-vue'
import {
  // queryModelList,
  deleteModel,
  trainModel,
  killTraining,
  exportToFolder,
  searchModel,
  // queryModelDetail
} from '@/api/model'
import DataViewStore from '@/store/modules/dataview'

@Component({
  components: { ModelTrainning },
})
export default class TrainningView extends Vue {
  private projectId: number = 0 // 项目 Id
  public columns = [
    {
      title: '模型名称',
      key: 'name',
      dataIndex: 'name',
      scopedSlots: { customRender: 'name' },
      // sorter: (a: { name: string }, b: { name: string }) =>
      //   a.name > b.name,
      sorter: (a: { name: string }, b: { name: string }) =>
        a.name > b.name ? 1 : -1,
      sortDirections: ['descend', 'ascend'],
    },
    {
      title: '模型类型',
      key: 'modelType',
      dataIndex: 'modelType',
      scopedSlots: { customRender: 'modelType' },
      // sorter: (a: { name: string }, b: { name: string }) =>
      //   a.name > b.name,
      sorter: (
        a: { modelType: string; algorithm: string },
        b: { modelType: string; algorithm: string }
      ) =>
        `${a.modelType}-${a.algorithm}` > `${b.modelType}-${b.algorithm}`
          ? 1
          : -1,
      sortDirections: ['descend', 'ascend'],
    },
    {
      title: '数据集',
      dataIndex: 'sourceName',
      key: 'sourceName',
      scopedSlots: { customRender: 'sourceName' },
      sorter: (a: { sourceName: string }, b: { sourceName: string }) =>
        a.sourceName > b.sourceName ? 1 : -1,
      sortDirections: ['descend', 'ascend'],
    },
    {
      title: '创建时间',
      dataIndex: 'gmtCreate',
      key: 'gmtCreate',
      defaultSortOrder: 'descend',
      sorter: (a: { gmtCreate: string }, b: { gmtCreate: string }) =>
        Date.parse(a.gmtCreate) - Date.parse(b.gmtCreate),
    },
    {
      title: '更新时间',
      dataIndex: 'gmtModify',
      key: 'gmtModify',
      defaultSortOrder: 'descend',
      sorter: (a: { gmtModify: string }, b: { gmtModify: string }) =>
        Date.parse(a.gmtModify) - Date.parse(b.gmtModify),
    },
    {
      title: '模型效果',
      key: 'data',
      dataIndex: 'data',
      scopedSlots: { customRender: 'data' },
    },
    {
      title: '训练时长',
      key: 'runTime',
      dataIndex: 'runTime',
      scopedSlots: { customRender: 'runTime' },
      defaultSortOrder: 'descend',
      sortDirections: ['descend', 'ascend'],
      sorter: (a: { runTime: any }, b: { runTime: any }) =>
        a.runTime > b.runTime ? 1 : -1,
    },
    {
      title: '操作',
      key: 'operate',
      scopedSlots: { customRender: 'action' },
    },
  ]
  public modelList = []
  public trainType: string = 'all'
  public reportUrl: string | null = null
  public createMode: boolean = false
  public modelForm: any = {}
  public collectionList: any = []
  public exportVisible: boolean = false
  public loading: boolean = false
  public modelIndex: any = {}
  public modelTypeList: any = [
    {
      groupName: '回归',
      options: [
        { key: 'LR', value: '线性(Linear Regression)' },
        { key: 'AUTOR', value: '自动机器学习(Auto Regression)' },
      ],
    },
    {
      groupName: '分类',
      options: [
        { key: 'DTC', value: '决策树(Decision Tree Classification)' },
        { key: 'AUTOC', value: '自动机器学习(Auto Classification)' },
      ],
    },
    {
      groupName: '聚类',
      options: [{ key: 'KM', value: 'K均值(K-Means)' }],
    },
    {
      groupName: '降维',
      options: [{ key: 'PCA', value: '主成分分析(PCA)' }],
    },
  ]
  public searchFm: any = {
    modelType: undefined,
    searchKey: '',
  }
  public tableLoading: boolean = false

  public get pipelineId() {
    return DataViewStore.getPipelineId
  }

  public get nowTime() {
    const nowTime = new Date()
    const month = (nowTime.getMonth() + 1).toString().padStart(2, '0')
    const startDate = nowTime.getDate().toString().padStart(2, '0')
    const time: any = `${nowTime.getFullYear()}-${month}-${startDate} ${nowTime.getHours()}:${nowTime.getMinutes()}:${nowTime.getSeconds()}`
    return time
  }

  public progressObj: any = {}
  public myProgress: any
  public progress = 0
  public getProgress(record: any) {
    // clearTimeout(this.myProgress)

    setTimeout(() => {
      this.updateProgress(record)
      // console.log(record.id,this.progressObj[record.id])
    }, 1000)
  }

  public updateProgress(list: any) {
    const nowTime = new Date().getTime()
    list.forEach((model: any) => {
      if (
        (model.algorithm === 'AUTOR' || model.algorithm === 'AUTOC') &&
        model.status === 'RUNNING'
      ) {
        // if (!this.progressObj[model.id]){
        const startTime = new Date(model.trainTime).getTime()
        this.$set(
          this.progressObj,
          model.id,
          Number(((nowTime - startTime) / 10 / model.param.timeout).toFixed(2))
        )

        // this.progressObj[model.id] = (nowTime-startTime)/10/model.param.timeout
      }
    })

    const kk = Object.values(this.progressObj).some(
      (progress: any) => progress < 100
    )
    if (kk) {
      this.getProgress(list)
    }
  }

  public get allModels() {
    return DataViewStore.modelList
  }
  @Watch('allModels', { deep: true })
  public modelChange() {
    console.log('status change')
    // clearTimeout(this.myProgress)
    this.queryList(this.trainType)
  }

  public async queryOperatorList() {
    const response = await allOperatorList({
      data: { projectId: this.projectId },
    })
    if (response.data.code === 100) {
      this.collectionList = []
      this.collectionList.push({
        id: '我的模型',
        name: response.data.result.panel.slice(-1)[0].name,
      })
      response.data.result.panel.slice(-1)[0].items.forEach((element: any) => {
        if (element.isFolder) {
          this.collectionList.push({ id: element.id, name: element.name })
        }
      })
      DataViewStore.setOperatorList(response.data.result.panel)
    }
  }

  @Watch('trainType')
  public async trainTypeChange(type: any) {
    if (type === 'all') {
      this.queryList(null)
    } else {
      this.queryList(type)
    }
  }

  public mounted() {
    this.queryList(null)
    this.queryOperatorList()
  }

  public created() {
    this.projectId = Number(this.$route.params.id)
    this.reportUrl = this.$route.path.replace(/trainning/, 'report')
  }

  public async queryList(type: any) {
    this.tableLoading = true

    try {
      const response = await searchModel({
        // data: { projectId: this.projectId,id:this.pipelineId },
        data: {
          projectId: this.projectId,
          ...this.searchFm,
          status: type === 'all' ? null : type,
        },
      })
      this.tableLoading = false
      if (response.data.code === 100) {
        this.modelList = response.data.result
        this.getProgress(this.modelList)
      }
    } catch {
      clearTimeout(this.myProgress)
      this.tableLoading = false
    }
  }

  public async deleteModel(record: any) {
    const that = this
    Modal.confirm({
      title: `确定要删除${record.name}吗？`,
      content: '删除将不会影响已导出的模型。',
      okText: '确定',
      cancelText: '取消',
      centered: true,
      async onOk() {
        const response = await deleteModel({
          // data: { projectId: this.projectId,id:this.pipelineId },
          data: {
            projectId: that.projectId,
            id: record.id,
            data: {},
          },
        })
        if (response.data.code === 100) {
          that.$message.success('删除成功！')
          that.queryList(that.trainType)
        }
      },
    })
  }

  public goCreate(record: any) {
    // this.$router.push(`/createmodel?id=${record.id}`)
    this.$router.push(
      this.$route.path.replace(/trainning/, `create?id=${record.id}`)
    )
  }

  public async startTrain(record: any) {
    this.loading = true
    this.$message.info('开始训练')
    const response = await trainModel({
      data: {
        id: record.id,
      },
    })
    this.loading = false
    if (response.data.code === 100) {
      this.$message.success('开始训练成功！')
    }
    this.queryList(null)
  }

  public reStartTrain(record: any) {
    this.$router.push(
      this.$route.path.replace(/trainning/, `create?id=${record.id}&current=1`)
    )
  }

  public exportData(record: any) {
    this.exportVisible = true
    this.modelIndex = record
  }

  public checkDataSource(record: any) {
    this.$router.push(
      this.$route.path.replace(
        /trainning/,
        `source?id=${record.sourceId}&name=${record.sourceName}`
      ) // chuan table id
    )
  }

  public createModel() {
    // this.createMode = !this.createMode
    // if (!this.createMode) {
    //   this.queryList(null)
    // }
    this.$router.push(this.$route.path.replace(/trainning/, 'create'))
  }

  public async cancelTrain(record: any) {
    // this.current += 1
    this.loading = true
    const response = await killTraining({
      data: {
        id: record.id,
        projectId: this.projectId,
      },
    })
    this.loading = false
    if (response.data.code === 100) {
      this.queryList(this.trainType)
      this.$message.success('取消训练成功！')
    }
  }

  public async search() {
    const response = await searchModel({
      data: { projectId: this.projectId, ...this.searchFm },
    })
    if (response.data.code === 100) {
      this.modelList = response.data.result
    }
  }

  public getRunTime(trainTime: any) {
    console.log(this.nowTime, trainTime)
    // console.log(Date.parse(this.nowTime) -Date.parse(trainTime))
  }

  public closeGraphPanel() {
    this.$router.push({ name: '数据视图' })
  }

  public viewConfig(record: any) {
    this.$router.push(
      this.$route.path.replace(
        /trainning/,
        `config?id=${record.id}&type=trainning`
      ) // chuan table id
    )
  }

  public async handleConfirm() {
    if (!this.modelForm.id) {
      this.$message.error('请选择文件夹！')
      return
    }
    let FOLDER_ID = this.modelForm.id
    if (this.modelForm.id === '我的模型') {
      FOLDER_ID = ''
    }
    const response = await exportToFolder({
      data: {
        projectId: this.projectId,
        id: this.modelIndex.id,
        folderId: FOLDER_ID,
        name: this.modelForm.name,
        modelDesc: this.modelForm.modelDesc,
      },
    })
    this.exportVisible = false
    this.modelForm = {}
    if (response.data.code === 100) {
      this.$message.success('导出成功！')
    }
  }
}
</script>

<style lang="less" scoped>
@import '@/styles/model';

.ant-radio-group-solid
  .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled) {
  background: #6973ff;
  border-color: #6973ff;
  color: #fff;
}

.ant-radio-button-wrapper:hover {
  background-color: #f0f1ff;
  color: #6973ff;
  position: relative;
}

/deep/ .ant-form-item-label {
  line-height: 32px;
}

/deep/ .ant-form-item-control {
  line-height: 32px;
}
</style>
